package com.zmn.oms.third.tc58.service.impl;

import com.github.ltsopensource.core.json.JSON;
import com.zmn.common.constant.StatusConsts;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.oms.business.interfaces.notifylog.OrderNotifyLogBService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderLogConsts;
import com.zmn.oms.common.constant.OrderStatusConsts;
import com.zmn.oms.common.dto.ResultDTO;
import com.zmn.oms.common.enums.ChannelFacade;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.model.entity.master.OrderMaster;
import com.zmn.oms.model.entity.notifylog.OrderNotifyLog;
import com.zmn.oms.model.entity.order.OrderExtend;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.entity.work.OrderWorkLogChange;
import com.zmn.oms.services.interfaces.detail.OrderDetailService;
import com.zmn.oms.services.interfaces.master.OrderMasterService;
import com.zmn.oms.services.interfaces.order.OrderExtendService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.third.base.dto.api.ApiInvokResult;
import com.zmn.oms.third.base.util.MasterPhoneUtil;
import com.zmn.oms.third.core.tracker.FacadeTracker;
import com.zmn.oms.third.tc58.Tc58ApiInvoker;
import com.zmn.oms.third.tc58.Tc58Consts;
import com.zmn.oms.third.tc58.dto.Tc58ExtOuterData;
import com.zmn.oms.third.tc58.service.Tc58Service;
import com.zmn.oms.zmn.business.interfaces.open.OrderChangeNotifyService;
import com.zmn.oms.zmn.business.interfaces.open.OrderNewNotifyService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 类描述：向58同城VIP推送订单变化通知的服务
 *
 * @author lhl
 * @date 2019/09/25 23:24
 */
@Slf4j
@Service("tc58NotifyService")
public class Tc58NotifyServiceImpl implements OrderChangeNotifyService, OrderNewNotifyService {

    @Autowired
    private OrderNotifyLogBService orderNotifyLogBService;
    @Autowired
    private OrderWorkService orderWorkService;
    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private OrderMasterService orderMasterService;
    @Autowired
    private OrderExtendService orderExtendService;
    @Autowired
    private Tc58Service tc58Service;

    @Override
    public void notifyChange(OrderWorkLogChange orderWorkLogChange) {
        if (!Tc58Consts.POWER_ON) {
            log.info("【{}】<订单状态同步> 该功能没有开启。", Tc58Consts.CHANNEL_NAME);
            return;
        }

        Tc58Consts.ChannelInfo channelInfo = Tc58Consts.getChannelInfo(orderWorkLogChange.getChannelId());
        String appkey = channelInfo.isJingxuan()
                ? Tc58ExtOuterData.fromExtOuterData(orderWorkLogChange.getExtOuterData()).getBUserId()
                : Tc58Consts.APPKEY;
        int logType = orderWorkLogChange.getLogType().intValue();

        // 修改/确认
        if (OrderLogConsts.ORDER_LOG_TYPE_UPDATE == logType || OrderLogConsts.ORDER_LOG_TYPE_CONFIRM == logType) {
            // 针对首次同步接单失败的情况，可通过“修改”操作，再次触发同步接单状态
            syncAcceptOrder(orderWorkLogChange, appkey);
        }
        // 派单
        else if (OrderLogConsts.ORDER_LOG_TYPE_DISTRIBUTE == logType) {
            syncMaster(orderWorkLogChange, appkey);
        }
        // 取消、失败、弃单
        else if (OrderLogConsts.ORDER_LOG_TYPE_CANCEL == logType || OrderConsts.ORDER_OP_TYPE_FAIL == logType
                || OrderConsts.ORDER_OP_TYPE_DISCARD == logType) {
            syncOrderCancel(orderWorkLogChange, appkey);
        }
        // 完成
        else if (OrderLogConsts.ORDER_LOG_TYPE_COMPLETE == logType) {
            syncOrderComplete(orderWorkLogChange, appkey);
        }
    }

    @Override
    public void notifyNewOrder(OrderWorkLogChange orderWorkLogChange) throws OmsBaseException {
        if (!Tc58Consts.POWER_ON) {
            log.info("【{}】<订单状态同步> 该功能没有开启。", Tc58Consts.CHANNEL_NAME);
            return;
        }

        Tc58Consts.ChannelInfo channelInfo = Tc58Consts.getChannelInfo(orderWorkLogChange.getChannelId());

        if (channelInfo.isJingxuan()) {
            OrderExtend dbOrderExtend = orderExtendService.findMiniOrderExtendByOrderId(orderWorkLogChange.getWorkId());
            if (NumberUtil.isNotNullOrZero(dbOrderExtend.getClueId())) {
                log.info(
                        "【{}】CDS录入订单，由CDS负责接单，orderWorkLogChange=[{}]",
                        Tc58Consts.CHANNEL_NAME,
                        JSON.toJSONString(orderWorkLogChange)
                );
                return;
            }
            Tc58ExtOuterData tc58ExtOuterData = Tc58ExtOuterData.fromExtOuterData(orderWorkLogChange.getExtOuterData());
            syncAcceptOrder4Jingxuan(orderWorkLogChange, tc58ExtOuterData.getBUserId());
        }
        else {
            syncAcceptOrder(orderWorkLogChange, Tc58Consts.APPKEY);
        }
    }

    /**
     * 同步接单状态
     * @param orderWorkLogChange
     */
    private void syncAcceptOrder(OrderWorkLogChange orderWorkLogChange, String appkey) {
        FacadeTracker.FacadeTrackerCore tracker = FacadeTracker.getTracker()
                .dataOut(ChannelFacade.TONGCHENG_58)
                .orderId(orderWorkLogChange.getOrderId())
                .remark("回复确认接单");

        Long orderId = orderWorkLogChange.getOrderId();

        // 查看同步记录，对已经同步接单成功的，不需要再次同步
        List<OrderNotifyLog> orderNotifyLogs = orderNotifyLogBService.listByOrderId(orderId);
        String orderNotifyStatus = String.valueOf(OrderStatusConsts.ORDER_STATUS_INPUT);
        if (orderNotifyLogs != null ) {
            for (OrderNotifyLog item : orderNotifyLogs) {
                if (Objects.equals(orderNotifyStatus, item.getNotifyStatus())
                        && Objects.equals(StatusConsts.STATUS_SUCCESS, item.getNotifyResultStatus())) {
                    // 对已经同步接单成功的，不需要再次同步
                    tracker.discard();
                    return;
                }
            }
        }

        Map<String, Object> data = new HashMap<>();
        data.put("clientId", appkey);
        data.put("orderId", orderWorkLogChange.getOuterId());
        data.put("flag", 1);    // flag:1接单、2不接单、3取消单

        ApiInvokResult result = Tc58ApiInvoker.apiInvok(Tc58Consts.PATH_ACCEPT_ORDER, data, Boolean.class);
        tracker.success(result.isSuccess()).commit();

        saveSyncResult(orderWorkLogChange, OrderStatusConsts.ORDER_STATUS_INPUT, result);
    }

    /**
     * 同步接单状态,"到家精选"渠道订单
     * @param orderWorkLogChange
     */
    private void syncAcceptOrder4Jingxuan(OrderWorkLogChange orderWorkLogChange, String appkey) {
        FacadeTracker.FacadeTrackerCore tracker = FacadeTracker.getTracker()
                .dataOut(ChannelFacade.TONGCHENG_58)
                .orderId(orderWorkLogChange.getOrderId())
                .remark("回复确认接单");

        Long orderId = orderWorkLogChange.getOrderId();

        // 查看同步记录，对已经同步接单成功的，不需要再次同步
        List<OrderNotifyLog> orderNotifyLogs = orderNotifyLogBService.listByOrderId(orderId);
        String orderNotifyStatus = String.valueOf(OrderStatusConsts.ORDER_STATUS_INPUT);
        if (orderNotifyLogs != null ) {
            for (OrderNotifyLog item : orderNotifyLogs) {
                if (Objects.equals(orderNotifyStatus, item.getNotifyStatus())
                        && Objects.equals(StatusConsts.STATUS_SUCCESS, item.getNotifyResultStatus())) {
                    // 对已经同步接单成功的，不需要再次同步
                    tracker.discard();
                    return;
                }
            }
        }

        Map<String, Object> data = new HashMap<>();
        data.put("clientId", appkey);
        data.put("orderId", orderWorkLogChange.getOuterId());
        data.put("flag", 1);    // flag:1接单、2不接单、3取消单
        /*
        refuseReason:拒单时传
            0：非拒单时传这个值
            1：疫情期间，小区不允许外部人员进入
            2：疫情期间，无法提供服务
            3：这个时间段已经约满
            4：暂时无法提供这个服务
            5：暂时不支持这个小区的服务
            6：联系不到您
         */
        data.put("refuseReason", 0);

        ApiInvokResult result = Tc58ApiInvoker.apiInvok(Tc58Consts.PATH_ACCEPT_ORDER_JX, data, Boolean.class);
        tracker.success(result.isSuccess()).commit();

        saveSyncResult(orderWorkLogChange, OrderStatusConsts.ORDER_STATUS_INPUT, result);

        // 同步接单成功后，获取用户联系电话，并将订单置为可操作状态
        if (result.isSuccess()) {
            tc58Service.activeJingxuanOrder(orderWorkLogChange);
        }
    }

    /**
     * 同步工程师信息
     * @param orderWorkLogChange
     */
    private void syncMaster(OrderWorkLogChange orderWorkLogChange, String appkey) {
        FacadeTracker.FacadeTrackerCore tracker = FacadeTracker.getTracker()
                .dataOut(ChannelFacade.TONGCHENG_58)
                .orderId(orderWorkLogChange.getOrderId())
                .remark("同步工程师信息");

        Long orderId = orderWorkLogChange.getOrderId();
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, orderId);

        // 查领单工程师
        List<OrderMaster> masterList = orderMasterService.listMasterByWorkId(orderWork.getOrderId(), orderWork.getWorkId());
        OrderMaster master = null;
        Integer masterId = orderWork.getMasterId();
        for (OrderMaster item : masterList) {
            if (item.getMasterId().equals(masterId)) {
                master = item;
                break;
            }
        }

        ApiInvokResult result = null;

        if (master == null) {
            log.info("【{}】同步工程师信息失败，没找到对应工程师。 orderId：[{}]，masterId：[{}]",
                    Tc58Consts.CHANNEL_NAME, orderId, masterId);

            result = new ApiInvokResult();
            result.setSuccess(false);
            result.setMsg(String.format("No Master found! masterId:[%d]", masterId));
        }
        else {
            Map<String, Object> data = new HashMap<>();
            data.put("clientId", appkey);
            data.put("orderId", orderWork.getOuterId());
            data.put(
                    "staffName",
                    Optional.ofNullable(master.getMasterName())
                            .filter(name -> name.length() >= 1)
                            .map(name -> String.format("%s工程师", name.substring(0,1)))
                            .orElse("工程师")
            );
            data.put("staffPhone", MasterPhoneUtil.getSafeMasterPhone(orderWork.getCityId()));
            data.put(
                    "staffPhone",
                    Optional.ofNullable(orderDetailService.findOrderDetailByKey(orderWork.getOrderId()))
                            .map(orderDetail -> {
                                if (Objects.equals(orderDetail.getBindStatus(), OrderConsts.BIND_STATUS_BIND)
                                        && org.apache.commons.lang3.StringUtils.isNotBlank(orderDetail.getBindTelephone())) {
                                    return orderDetail.getBindTelephone();
                                }
                                return null;
                            })
                            .orElse(MasterPhoneUtil.getSafeMasterPhone(orderWork.getCityId()))
            );

            result = Tc58ApiInvoker.apiInvok(Tc58Consts.PATH_MASTER_INFO, data, Boolean.class);
        }
        tracker.success(result.isSuccess(), result.getMsg()).commit();

        saveSyncResult(orderWorkLogChange, OrderStatusConsts.ORDER_STATUS_DISTRIBUTE, result);
    }

    /**
     * 同步订单完成
     * @param orderWorkLogChange
     */
    private void syncOrderComplete(OrderWorkLogChange orderWorkLogChange, String appkey) {
        FacadeTracker.FacadeTrackerCore tracker = FacadeTracker.getTracker()
                .dataOut(ChannelFacade.TONGCHENG_58)
                .orderId(orderWorkLogChange.getOrderId())
                .remark("同步订单完成");

        String outerId = orderWorkLogChange.getOuterId();

        Map<String, Object> data = new HashMap<>();
        data.put("clientId", appkey);
        data.put("orderId", outerId);
        // serviceState:1 已分配服务人员 2 服务时间变更 3 开始服务 4 已完成
        data.put("serviceState", 4);

        ApiInvokResult result = Tc58ApiInvoker.apiInvok(Tc58Consts.PATH_ORDER_STATUS, data, Boolean.class);
        tracker.success(result.isSuccess(), result.getMsg()).commit();

        saveSyncResult(orderWorkLogChange, OrderStatusConsts.ORDER_STATUS_COMPLETE, result);
    }

    /**
     * 同步订单取消
     * @param orderWorkLogChange
     */
    private void syncOrderCancel(OrderWorkLogChange orderWorkLogChange, String appkey) {
        FacadeTracker.FacadeTrackerCore tracker = FacadeTracker.getTracker()
                .dataOut(ChannelFacade.TONGCHENG_58)
                .orderId(orderWorkLogChange.getOrderId())
                .remark("同步订单取消");

        String outerId = orderWorkLogChange.getOuterId();

        Map<String, Object> data = new HashMap<>();
        data.put("clientId", appkey);
        data.put("orderId", outerId);
        data.put("flag", 3);    // flag:1接单、2不接单、3取消单

        ApiInvokResult result = Tc58ApiInvoker.apiInvok(Tc58Consts.PATH_ACCEPT_ORDER, data, Boolean.class);
        tracker.success(result.isSuccess(), result.getMsg()).commit();

        saveSyncResult(orderWorkLogChange, OrderStatusConsts.ORDER_STATUS_CANCEL, result);
    }



    /**
     * 保存状态同步结果信息
     * @param orderWorkLogChange
     * @param orderStatus
     * @param result
     */
    @SuppressWarnings("all")
    private void saveSyncResult(OrderWorkLogChange orderWorkLogChange, int orderStatus, ApiInvokResult result) {
        if (result == null) {
            return;
        }

        OrderNotifyLog orderNotifyLog = new OrderNotifyLog();
        orderNotifyLog.setMqMsgKey(orderWorkLogChange.getMqMsgKey());
        orderNotifyLog.setOrderId(orderWorkLogChange.getOrderId());
        orderNotifyLog.setChannelId(orderWorkLogChange.getChannelId());
        orderNotifyLog.setOrderStatus(orderWorkLogChange.getStatus());
        orderNotifyLog.setOrderResultStatus(orderWorkLogChange.getResultStatus());
        orderNotifyLog.setNotifyStatus(String.valueOf(orderStatus));
        orderNotifyLog.setType(OrderConsts.ORDER_NOTIFY_TYPE_CHANGE);
        orderNotifyLog.setNotifyTime(DateUtil.getNow());
        orderNotifyLog.setNotifyResultMsg(String.format("[%s]-%s",
                OrderStatusConsts.getOrderStatusName(orderStatus), result.getMsg()));

        ResultDTO resultDTO = new ResultDTO();
        resultDTO.setStatus(result.isSuccess() ? StatusConsts.STATUS_SUCCESS : StatusConsts.STATUS_ERROR);
        resultDTO.setData(orderNotifyLog);

        orderNotifyLogBService.saveNotifyLog(resultDTO);
    }
}
